
from sketchz import *
from sdl2.ext import FontTTF
from frame import *

Rect = sdl2.SDL_Rect

font = FontTTF("MapleMonoNL-Regular.ttf", "20px", (40, 40, 40, 255))       # 尼玛这里就是255级的




window = Window2((1000, 800))
window.img.clear_value = (0.6, 0.7, 0.8, 1)


test = font.render_text("m")
stdw, stdh = test.w, test.h
print(stdw, stdh)

startx, starty = 300, 300

# ~ code = """
# ~ for i in range(10):
    # ~ for j in range(10):
        # ~ print(i + j)
# ~ """.strip().split("\n")

# ~ code = """
# ~ x333-x3-y3-z3
# ~ """.strip().split("\n")
code = """
pd1 = [0.45, 0.2, 0.3, pi/8, 0.1, 0, 0, 0]
pd2 = [-0.45, 0.2, 0.3, -pi/8, 0.1, 0, 0, 0]
pd3 = [0.45, -0.2, 0.3, -pi/8, 0.1, 0, 0, 0]
pd4 = [-0.45, -0.2, 0.3, pi/8, 0.1, 0, 0, 0]
def space(window, k):
    pass
""".strip().split("\n")


def retext():
    sdl2.ext.draw.fill(window.screen, 0)
    for i, line in enumerate(code):
        if len(line) == 0:      # 渲染空字符串会报错
            continue
        text = font.render_text(line)
        sdl2.SDL_BlitSurface(text, None, window.screen, Rect(startx, starty + i * stdh, 800, 800))
    window.flush_screen()

retext()

def calc(line, pos):
    return startx + stdw * pos, starty + stdh * line

def calc_inv(x, y):
    return (y - starty) // stdh, (x - startx) // stdw

def calc_inv2(x, y):
    return  (y - starty) / stdh, (x - startx) / stdw


# ~ box = make_block(U3(1,1,1))
# ~ box.color = V3(1, 1, 1) * 0.9
# ~ box.prog = prog1_mc
# ~ box.u(window)
# ~ box >> window

# ~ window.camera.t.pos = U3(1, -7,1)   # block用
window.camera.t.pos = U3(1, 7,1)        # face用
viewer = Viewer(window.camera)
viewer >> window
viewer.unreg_event(window)

edit_buffer = np.zeros((100, 100, 4), dtype="uint8")
cursor = [0, 0]


class Ctrl(Control):
    def down(self, window, e):
        if e.keysym.sym == sdl2.SDLK_ESCAPE: #sdl2.SDLK_BACKQUOTE:
            if viewer.wheel in window.wheel_callback:
                viewer.unreg_event(window)
                window.render2d.uniform_buffer.write(np.array([0, 0.1, -0.99, 1], dtype="f4").tobytes())
                editctrl >> window
                blin >> window

                print("event forbidden")
            else:
                viewer.reg_event(window)
                window.render2d.uniform_buffer.write(np.array([0, 0.1, 0.99, 0.4], dtype="f4").tobytes())
                editctrl.unreg_event(window)

                if blin.update in window.update_callback:
                    blin.unreg_event(window)
                edit_buffer[:, :, 0] = 0
                blin.force()


                print("event enable")
            return True




    def reg_event(self, window):
        window.key_down_callback.append(self.down)
        editctrl >> window
        blin >> window


    def unreg_event(self, window):
        window.key_down_callback.remove(self.down)
        if viewer.wheel not in window.wheel_callback:
            viewer >> window
        if editctrl.mouse_down in window.mouse_down_callback:
            editctrl.unreg_event(window)

        if blin.update in window.update_callback:
            blin.unreg_event(window)
        edit_buffer[:, :, 0] = 0
        blin.force()



class EditCtrl(Control):
    def mouse_down(self, window, e):
        l, p = calc_inv(e.x, e.y)
        print(l, p)
        try:
            ch = code[l][p]
            print(ch)
            edit_buffer[:, :, 0] = 0
            cursor[0] = l
            cursor[1] = p
            blin.force()
        except Exception:
            pass

    def text(self, window, e):
        ch = e.text.decode("utf8")
        if ch in "abcdefghijlmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()~`_-+={}[]|\\;:'\"?/>.<,":
            cl, cp = cursor
            s = list(code[cl])
            s[cp:cp] = ch
            code[cl] = ''.join(s)
            retext()
            cursor[1] += 1
            edit_buffer[:, :, 0] = 0
            blin.force()
            plugin_wake()

        return True

    def keydown(self, window, e):
        flag = True # 用于，如果检测到按键，更新blin的闪烁情况
        if e.keysym.sym == sdl2.SDLK_BACKSPACE:
            cl, cp = cursor
            s = list(code[cl])
            if cursor[1] != 0:
                s[cp-1:cp] = []
                code[cl] = ''.join(s)
                cursor[1] -= 1

                retext()
                edit_buffer[:, :, 0] = 0
                blin.force()
                plugin_wake()
            else:
                if cursor[0] != 0:
                    # 回到上一行
                    te = code[cl]
                    del code[cl]
                    cl -= 1
                    cp = len(code[cl])
                    code[cl] += ''.join(te)
                    cursor[0], cursor[1] = cl, cp

                    retext()
                    edit_buffer[:, :, 0] = 0
                    blin.force()
                    plugin_wake()


            return True
        elif e.keysym.sym == sdl2.SDLK_DELETE:
            cl, cp = cursor
            s = list(code[cl])
            if cursor[1] != len(s):
                s[cp:cp+1] = []
                code[cl] = ''.join(s)

                retext()
                edit_buffer[:, :, 0] = 0
                blin.force()
                plugin_wake()
            return True
        elif e.keysym.sym == sdl2.SDLK_SPACE:
            cl, cp = cursor
            s = list(code[cl])
            s[cp:cp] = ' '
            code[cl] = ''.join(s)
            cursor[1] += 1

            retext()
            edit_buffer[:, :, 0] = 0
            blin.force()
            plugin_wake()
            return True
        elif e.keysym.sym == sdl2.SDLK_RETURN or e.keysym.sym == sdl2.SDLK_KP_ENTER :
            cl, cp = cursor
            s = list(code[cl])
            left, right = s[:cp], s[cp:]
            if len(right) > 0:
                code[cl] = ''.join(left)
                code[cl+1:cl+1] = [''.join(right)]
            else:
                code[cl] = ''.join(left)
                code[cl+1:cl+1] = ['']
            cursor[0] += 1
            cursor[1] = 0

            retext()
            edit_buffer[:, :, 0] = 0
            blin.force()
            plugin_wake()
            return True
        elif e.keysym.sym == sdl2.SDLK_UP:
            cl, cp = cursor
            if cl > 0:
                cl -= 1
            if cp > len(code[cl]):
                cp = len(code[cl])
            cursor[0] = cl
            cursor[1] = cp

            edit_buffer[:, :, 0] = 0
            blin.force()
        elif e.keysym.sym == sdl2.SDLK_DOWN:
            cl, cp = cursor
            if cl < len(code) - 1:
                cl += 1
            if cp > len(code[cl]):
                cp = len(code[cl])
            cursor[0] = cl
            cursor[1] = cp

            edit_buffer[:, :, 0] = 0
            blin.force()
        elif e.keysym.sym == sdl2.SDLK_LEFT:
            cl, cp = cursor
            if cp > 0:
                cp -= 1
            cursor[1] = cp

            edit_buffer[:, :, 0] = 0
            blin.force()
        elif e.keysym.sym == sdl2.SDLK_RIGHT:
            cl, cp = cursor
            if cp < len(code[cl]):
                cp += 1
            cursor[1] = cp

            edit_buffer[:, :, 0] = 0
            blin.force()
        elif e.keysym.sym == sdl2.SDLK_HOME:
            cursor[1] = 0

            edit_buffer[:, :, 0] = 0
            blin.force()
        elif e.keysym.sym == sdl2.SDLK_END:
            cl, cp = cursor
            cursor[1] = len(code[cl])

            edit_buffer[:, :, 0] = 0
            blin.force()
        else:
            flag = False

        if flag:
            blin.wake()


    def reg_event(self, window):
        sdl2.SDL_StartTextInput(True)
        window.mouse_down_callback.append(self.mouse_down)
        window.text_callback.append(self.text)
        window.key_down_callback.append(self.keydown)

    def unreg_event(self, window):
        sdl2.SDL_StopTextInput(True)
        window.mouse_down_callback.remove(self.mouse_down)
        window.text_callback.remove(self.text)
        window.key_down_callback.remove(self.keydown)

editctrl = EditCtrl()


class Blin(Control):
    def __init__(self):
        self.acc = 0
        self.b = True
        edit_buffer[0, 0, 0] = 255
        # ~ edit_buffer[1, 5, 0] = 255

        self.running = True
        self.force()


    def update(self, window, dt):
        if self.running == False:
            return

        self.acc += dt
        if self.acc > 0.5:
            # ~ print("tick1")
            self.acc = 0
            self.b = not self.b
            cl, cp = cursor
            edit_buffer[cl, cp, 0] = 255 - edit_buffer[cl, cp, 0]
            self.force()

    def wake(self):
        self.acc = 0.5

    def force(self):
        window.render2d.texture2.write(edit_buffer.tobytes())

    def reg_event(self, window):
        window.update_callback.append(self.update)

    def unreg_event(self, window):
        window.update_callback.remove(self.update)

blin = Blin()


Ctrl() >> window


# plugin

# 为了导入，骚啊
import importlib, sys
# ~ sys.path.append("./plugins/box_lang/")
# ~ plugin = importlib.import_module("plugin_main")
# ~ sys.path.remove("./plugins/box_lang/")
sys.path.append("./plugins/eyes/")
plugin = importlib.import_module("plugin_main")
sys.path.remove("./plugins/eyes/")

plugin = plugin.Main(window)

def plugin_wake():    # call plugin
    plugin.reboot(code)

plugin_wake()

window.mainloop()
